﻿using System;
using CrateMayhem.Common.Services;

namespace CrateMayhem.Common.ViewModel
{
    public class GameViewModel : ViewModelBase
    {
        private readonly IAutoCloseDialogService autoCloseDialogService;
        private readonly IGameSettingsService gameSettingsService;
        private readonly IGameService gameService;
        private readonly IMessageService messageService;
        private int level;
        private int moves;
        private string moveList;
        private string totalMoves;
        
        public GameViewModel(IServiceFactory serviceFactory)
        {
            autoCloseDialogService = serviceFactory.Create<IAutoCloseDialogService>();
            gameSettingsService = serviceFactory.Create<IGameSettingsService>();
            gameService = serviceFactory.Create<IGameService>();
            messageService = serviceFactory.Create<IMessageService>();

            gameService.Finished += OnGameFinished;
            gameService.PushCompleted += OnPushCompleted;
            gameService.Retry += OnRetry;
            gameSettingsService.LevelsReset += OnLevelsReset;
            
            var lastCompletedLevel = gameSettingsService.FindLastLevel();

            if (lastCompletedLevel < 100) lastCompletedLevel++;

            Level = lastCompletedLevel;

            Moves = 0;
        }

        public int Level
        {
            get
            {
                return level;
            }
            private set
            {
                level = value;
                var world = gameService.Find(value);
                TotalMoves = world != null ? world.TotalMoves + " moves" : "";
                OnPropertyChanged("Level");
            }
        }

        public int Moves
        {
            get
            {
                return moves;
            }
            set
            {
                moves = value;

                if (moves == 0) moveList = null;
                OnPropertyChanged("Moves");
            }
        }

        public string TotalMoves
        {
            get
            {
                return totalMoves;
            }
            set
            {
                totalMoves = value;
                OnPropertyChanged("TotalMoves");
            }
        }

        private void OnRetry(object sender, EventArgs e)
        {
            Moves = 0;
            var currentLevel = Level;
            Level = 0;
            Level = currentLevel;
        }

        private void OnGameFinishedWindowClosed(object sender, EventArgs e)
        {
            autoCloseDialogService.Closed -= OnGameFinishedWindowClosed;
            Level++;
            Moves = 0;
            gameService.Finished += OnGameFinished;
        }

        private void OnPushCompleted(object sender, PushCompletedEventArgs args)
        {
            if (args.Pushed)
            {
                moveList += args.Move.ToString()[0];
                Moves = moveList.Length;
            }
        }

        private void OnGameFinished(object sender, EventArgs args)
        {
            gameService.Finished -= OnGameFinished;

            if (Level + 1 > 100)
            {
                autoCloseDialogService.ShowDialog("You've completed all the levels. Well done");
            }
            else
            {
                gameSettingsService.Save(Level, moveList);
                autoCloseDialogService.Closed += OnGameFinishedWindowClosed;
                autoCloseDialogService.ShowDialog(messageService.RandomSuccess(), 2000);
            }
        }

        private void OnLevelsReset(object sender, EventArgs eventArgs)
        {
            Level = 1;
            Moves = 0;
        }
    }
}
